package com.strive.controller;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.strive.common.result.Result;
import com.strive.common.val.Const;
import com.strive.entity.SysRole;
import com.strive.entity.SysRoleMenu;
import com.strive.entity.SysUserRole;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author strive.Peng
 * @since 2024-03-14
 */
@RestController
@RequestMapping("/sys/role")
public class SysRoleController extends BaseController {

    /**
     * 通过id查找衣蛾角色的详细信息
     *
     * @param id 角色id
     * @return 返回一个角色信息
     */
    @GetMapping("/info/{id}")
    @PreAuthorize("hasAuthority('sys:role:list')")
    public Result info(@PathVariable(name = "id") Long id) {
        // 查找用户信息
        SysRole sysRole = sysRoleService.getById(id);

        // 查找角色关联的菜单
        List<SysRoleMenu> roleMenus = sysRoleMenuService.list(new QueryWrapper<SysRoleMenu>().eq("role_id", id));
        // 以流的方式提取 与角色相关联的菜单 设置属性
        List<Long> menusIds = roleMenus.stream().map(p -> p.getMenuId()).collect(Collectors.toList());
        sysRole.setMenuIds(menusIds);

        // 返回的数据就是一个完整的包含菜单信息的角色信息
        return Result.success(sysRole);
    }

    /**
     * 查询功能的实现
     * 拥有分页的功能
     *
     * @param name 查询条件 传入的角色名称
     * @return 返回一个查询的结果
     */
    @GetMapping("/list")
    @PreAuthorize("hasAuthority('sys:role:list')")
    public Result list(String name) {
        // 分页查询 前端点击分页通过 getPage方法得到当前页面传入插叙条件中实现刷新
        Page<SysRole> pageData = sysRoleService.page(getPage(),
                new QueryWrapper<SysRole>()
                        // 查询前进行条件判断 name是否为空
                        .like(StrUtil.isNotBlank(name), "name", name));
        return Result.success(pageData);
    }

    /**
     * 保存角色信息
     *
     * @param sysRole 前端传来的表单信息
     * @return 返回了一个表单信息
     */
    @PostMapping("/save")
    @PreAuthorize("hasAuthority('sys:role:save')")
    public Result save(@Validated @RequestBody SysRole sysRole) {
        // 已经通过了校验，直接保存到数据库中
        sysRole.setCreated(LocalDateTime.now());
        sysRole.setStatu(Const.STATUTS_ON);

        sysRoleService.save(sysRole);
        return Result.success(sysRole);
    }

    /**
     * 角色编辑的更新操作
     *
     * @param sysRole
     * @return
     */
    @PostMapping("/update")
    @PreAuthorize("hasAuthority('sys:role:update')")
    public Result update(@Validated @RequestBody SysRole sysRole) {
        sysRole.setUpdated(LocalDateTime.now());
        // 根据ID保存
        sysRoleService.updateById(sysRole);

        // 更新缓存
        sysUserService.clearUserAuthorityInfoByRoleId(sysRole.getId());
        return Result.success(sysRole);
    }

    /**
     * 删除角色信息 批量删除角色信息
     *
     * @param ids
     * @return
     */

    @PostMapping("/delete")
    @PreAuthorize("hasAuthority('sys:role:delete')")
    @Transactional // 事务注解 保证事务的原子性 这后面的一部分操作必须全部完成
    public Result delete(@RequestBody Long[] ids) {

        // 调用批量删除的方法 传入的是一个数组，需要数组转集合
        sysRoleService.removeByIds(Arrays.asList(ids));

        // 更新中间表 删除中间表的记录
        sysUserRoleService.remove(new QueryWrapper<SysUserRole>().in("role_id", ids));
        sysRoleMenuService.remove(new QueryWrapper<SysRoleMenu>().in("role_id", ids));

        // 删除之后 需要更新缓存 缓存同步删除 循环删除
        Arrays.stream(ids).forEach(id -> {
            sysUserService.clearUserAuthorityInfoByRoleId(id);
        });

        return Result.success("");
    }

    /**
     * 分配角色的方法实现
     *
     * @param roleId  传来的角色id
     * @param menuIds 传来的分配的菜单id
     * @return 返回结果
     */

    @PostMapping("/perm/{roleId}")
    @PreAuthorize("hasAuthority('sys:role:perm')")
    @Transactional
    public Result prem(@PathVariable("roleId") Long roleId, @RequestBody Long[] menuIds) {
        // 添加新的角色菜单关联信息
        List<SysRoleMenu> roleMenusList = new ArrayList<>();
        Arrays.stream(menuIds).forEach(menuId -> {
            SysRoleMenu roleMenu = new SysRoleMenu();
            roleMenu.setMenuId(menuId);
            roleMenu.setRoleId(roleId);

            // 将这条数据添加到list中保存
            roleMenusList.add(roleMenu);
        });
        // 保存到数据库中(先删除原来的信息，再保存新的信息)
        sysRoleMenuService.remove(new QueryWrapper<SysRoleMenu>().eq("role_id", roleId));
        sysRoleMenuService.saveBatch(roleMenusList);

        // 删除缓存
        sysUserService.clearUserAuthorityInfoByRoleId(roleId);
        return Result.success(menuIds);
    }
}
